﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MySql.Data.MySqlClient;
using System.Data;
using System.Reflection;
using log4net;

namespace ProjectBuilder
{
    public class BaseDocObject : BaseObject
    {
        /// <summary>
        /// Ід папки в базі даних
        /// </summary>
        protected long? _dbId;

        [DbField("id", IsNullable = false)]
        public long? DBId
        {
            get { return _dbId; }
        }

        /// <summary>
        /// Функція повертає ІД об'єкта в БД, якщо такого нема, то створює його
        /// </summary>
        /// <returns>ІД об'єкта</returns>
        public long? GetDBId()
        {
            if (!_dbId.HasValue)
            {
                _dbId = saveToDb();
            }
            return _dbId;
        }

        /// <summary>
        /// Зберігає поточні значення об'єкту в БД
        /// </summary>
        /// <returns>ІД об'єкту в базі даних</returns>
        protected long saveToDb()
        {
            var fields = getFields(this, true);

            var tableName = this.getAttribute<DbTableAttribute>();
            if (tableName == null)
            {
                throw new Exception("Unknown table name");
            }

            var cmd = new MySqlCommand();
            var query = "SELECT id FROM `" + tableName.TableName + "` WHERE 1 = 1";
            foreach (var field in fields)
            {
                if (field.Value == null)
                {
                    query += " AND `" + field.Key + "` IS NULL";
                }
                else
                {
                    query += " AND `" + field.Key + "` = @" + field.Key;
                    cmd.Parameters.AddWithValue(field.Key, field.Value);
                }
            }
            cmd.CommandText = query;
            cmd.CommandType = CommandType.Text;
            cmd.Connection = Globals.Connection;
            LogManager.GetLogger("BaseDocObject").Debug("SQL: " + query);
            var reader = cmd.ExecuteReader();

            if (reader.HasRows)
            {
                reader.Read();
                var id = long.Parse(reader["id"].ToString());
                reader.Close();
                _dbId = id;
                Update();
                return id;
            }
            reader.Close();
            cmd.Parameters.Clear();

            /// Якщо об'єкту не існує в базі даних, то він створюється
            fields = getFields(this);
            var keys = new List<string>(fields.Keys);
            var names = "`" + string.Join("`, `", keys.ToArray()) + "`";
            var parameters = "@" + string.Join(", @", keys.ToArray());

            query = "INSERT INTO `" + tableName.TableName + "`(" + names + ") VALUES (";

            cmd = new MySqlCommand();
            var values = getQueryField(fields, ref cmd);
            query += string.Join(",", values.Values.ToArray());
            query += ");";

            cmd.CommandText = query;
            cmd.CommandType = CommandType.Text;
            cmd.Connection = Globals.Connection;
            LogManager.GetLogger("BaseDocObject").Debug("SQL: " + query);
            /*foreach (MySqlParameter param in cmd.Parameters)
            {
                LogManager.GetLogger("BaseDocObject").Debug("Param: " + param.ParameterName + " " + param.Value);
            }*/
            cmd.ExecuteNonQuery();
            return cmd.LastInsertedId;
        }

        /// <summary>
        /// Оновлює значення об'єкту в БД
        /// </summary>
        public void Update()
        {
            var fields = getFields(this);
            var keys = new List<string>(fields.Keys);
            var names = "`" + string.Join("`, `", keys.ToArray()) + "`";

            var tableName = this.getAttribute<DbTableAttribute>();
            if (tableName == null)
            {
                throw new Exception("Unknown table name");
            }

            var query = "UPDATE `" + tableName.TableName + "` SET ";

            var cmd = new MySqlCommand();
            var values = getQueryField(fields, ref cmd);
            var lst = new List<string>();
            foreach (var itm in values)
            {
                if (itm.Key == "new") continue;

                lst.Add(itm.Key + " = " + itm.Value);
            }
            query += string.Join(", ", lst.ToArray()) + " WHERE id = " + _dbId.Value + ";";

            cmd.CommandText = query;
            cmd.CommandType = CommandType.Text;
            cmd.Connection = Globals.Connection;
            LogManager.GetLogger("BaseDocObject").Debug("SQL: " + query);
            cmd.ExecuteNonQuery();
        }
    }
}
